package cn.octuc.ccu;

import android.util.Log;

import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

public class CUWebSocket {
    static String TAG = "ccu";

    WebSocket mWebSocket = null;
    CUWebSocketListener myWebSocketListener = null;
    String wsURL = "";
    OkHttpClient client;
    Request request;


    public void connectWebSocket(String wsUrl, CUWebSocketListener listener) {
        wsURL = wsUrl;
        myWebSocketListener = listener;

        TrustAllManager trustAllManager = new TrustAllManager();

        this.client = new OkHttpClient.Builder()
                .pingInterval(40, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .connectTimeout(60, TimeUnit.SECONDS)
                .hostnameVerifier(createTrustAllHostnameVerifier())
                .sslSocketFactory(createTrustAllSSLFactory(trustAllManager), trustAllManager)
                .retryOnConnectionFailure(true)
                .build();

        this.connection();

        //this.client.dispatcher().executorService().shutdown();
        Log.e(TAG, "connectWebSocket ==");
    }

    void connection() {
        try {
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (this.ping()) {
            return;
        }

        Log.e(TAG, "connection ...");
        this.request = new Request.Builder()
                .url(this.wsURL)
                .build();

        this.client.newWebSocket(request, new MyWebSocket());
    }

    public boolean ping() {
        if (mWebSocket == null) {
            Log.e(TAG, "sendString fail, mWebSocket is null");
            return false;
        }
        return this.mWebSocket.send("ping");
    }

    public boolean sendString(String data) {
        if (mWebSocket == null) {
            Log.e(TAG, "sendString fail, mWebSocket is null");
            return false;
        }

        Log.e(TAG, "sendString: " + data);
        return mWebSocket.send(data);
    }

    class MyWebSocket extends WebSocketListener {

        @Override
        public void onOpen(WebSocket webSocket, Response response) {
            super.onOpen(webSocket, response);
            mWebSocket = webSocket;
            Log.e(TAG, "11 onOpen: " + response);

            if (myWebSocketListener != null) {
                myWebSocketListener.onOpen();
            }
        }

        @Override
        public void onMessage(WebSocket webSocket, String text) {
            super.onMessage(webSocket, text);

            if (myWebSocketListener != null) {
                myWebSocketListener.onMessage(text);
            }
        }

        @Override
        public void onMessage(WebSocket webSocket, ByteString bytes) {
            super.onMessage(webSocket, bytes);
        }

        @Override
        public void onClosing(WebSocket webSocket, int code, String reason) {
            super.onClosing(webSocket, code, reason);
            Log.e(TAG, "11 onClosing: " + reason);
        }

        @Override
        public void onClosed(WebSocket webSocket, int code, String reason) {
            super.onClosed(webSocket, code, reason);
            Log.e(TAG, "11 onClosed: " + reason);

            if (myWebSocketListener != null) {
                myWebSocketListener.onClose();
            }
            connection();
        }

        @Override
        public void onFailure(WebSocket webSocket, Throwable t, Response response) {
            super.onFailure(webSocket, t, response);
            Log.e(TAG, "11 onFailure: " + response);

            if (myWebSocketListener != null) {
                myWebSocketListener.onError(String.format("%s", response));
            }

            connection();
        }
    }


    public class TrustAllManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }

    protected SSLSocketFactory createTrustAllSSLFactory(TrustAllManager trustAllManager) {
        SSLSocketFactory ssfFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{trustAllManager}, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception ignored) {
            ignored.printStackTrace();
        }

        return ssfFactory;
    }

    //获取HostnameVerifier
    protected HostnameVerifier createTrustAllHostnameVerifier() {
        return new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
    }
}
